library IEEE;
use IEEE.std_logic_1164.all;

entity TxUnit is
  port (
    clk, reset : in std_logic;
    enable : in std_logic;
    ld : in std_logic;
    txd : out std_logic;
    regE : out std_logic;
    bufE : out std_logic;
    data : in std_logic_vector(7 downto 0));
end TxUnit;

type state is (init, load_regE, start, data, stop);

architecture archTxUnit of TxUnit is

begin
	txd <= '1';
	process (enable, reset)
		variable myState : state := init;
		variable bufferE : std_logic_vector(7 downto 0);
		variable registerE : std_logic_vector(7 downto 0);
		
		-- Variables qui prennent les valeurs des sorties bufE et regE
		variable myBufE : std_logic := 1;
		variable myRegE : std_logic := 1;
		
		-- Variable datum for data transmission
		-- The value 8 is for the parity bit
		variable datum : integer range 0 to 8 := 0;
	
	begin
	    if (reset = '0') then
	        txd <= '1';
	        bufE <= '1';
	        regE <= '1';
	        myState := init;
	        datum := 0;
	    elsif (enable = '1' and enable'event) then
	        case myState is
	            when init =>
	                txd <= '1';
	                bufE <= '1';
	                regE <= '1';
	                datum := 0;
	                if (ld = '1' and myBufE = '1') then
	                -- load the data in the buffer
	                    bufferE := data;
	                    bufE <= '0';
	                    myBufE := 0; 
	                -- move to the next state
	                    myState := load_regE;
	                end if;
	                if (myBufE = '0') then
	                -- The buffer is full, move to the next state
	                    myState := load_regE;
	                end if;
	
	            when load_regE =>
	            -- load the buffer in the register
	                registerE := bufferE;
	                bufE <= '1';
	                regE <= '0';
	                myBufE := 1;
	                myRegE := 0;
	            -- move to state 'starting to send data'
	                myState := start;
	
	            when start =>
	            -- send the start bit 0
	                txd <= '0';
	            -- move to state 'data'
	                myState := data;
	                
	            when data =>
	            -- -----------------------------------------------
	            -- send the 8 bits of the register from MSB
	            -- (Most Significant Bit) to LSB
	            -- or the parity bit if transmission is finished
	            -- -----------------------------------------------
	            
	            -- !!!: The transmission of the data and the parity bit is
	            -- punctuated by enable              
	                
	                if(datum = 8) then
	                -- data transmission terminated
	                -- transmission of the parity bit
	                -- maybe there is a better way to do this
	                	txd <= 	data(0) xor
	                			data(1) xor
	                			data(2) xor
	                			data(3) xor
	                			data(4) xor
	                			data(5) xor
	                			data(6) xor
	                			data(7);
	                -- modification of the flags and the state
		                regE <= '1';
		                myRegE := '1';
		                myState := stop;
	                else
	                -- transmission of the datum data(datum)
	                	txd <= data(datum);
	                end if;
	                datum := (datum + 1) mod 9;
	                
	            when others =>
	            -- stop state
	            -- transmission of the stop bit
	                txd <= '1';
	            -- move to next state
	                if (myBufE = '0' or (ld = '1' and myBufE = '1')) then
	                    myState := load_regE;
	                else
	                    myState := init;
	                end if;
	        end case;
	    end if;
	end process
end archTxUnit;
